package com.swfgui.queue
{
	import com.swfgui.utils.ArrayUtil;
	
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;

	/**
	 * 执行队列，按时间顺序自动执行操作
	 * @author liulijun
	 */
	public class OperationQueue extends EventDispatcher
	{
		private var opArr:Array;
		private var allOpArr:Array;
		private var parallelArr:Array;
		private var canExe:Boolean = true;
		private var curOp:Operation;
		private var _isExeing:Boolean;

		public function OperationQueue()
		{
			allOpArr = [];
			opArr = [];
			parallelArr = [];
		}

		public function get isNull():Boolean
		{
			return (opArr.length == 0);
		}

		public function clear():void
		{
			canExe = true;
			curOp = null;
			opArr.length = 0;
			parallelArr.length = 0;
			for each(var op:Operation in allOpArr)
			{
				op.target.removeEventListener(OperationEvent.COMPLETE, opCpt);
			}
			allOpArr.length = 0;
		}

		/**
		 * 顺序执行多个操作，每个操作执行完毕以后，会发出OperationEvent.COMPLETE事件。
		 * @param target 派发OperationEvent.COMPLETE，执行后续功能
		 * @param opFunction 要执行的函数
		 * @param argArray 函数参数
		 * @param parallel 相邻的n个parallel为true的操作，会同时执行，
		 * 当n个操作全部都执行完毕以后，才继续执行后续操作。
		 */
		public function push(target:EventDispatcher, opFunction:Function, argArray:Array=null, parallel:Boolean = false):void
		{
			if (!target || opFunction==null)
			{
				return;
			}

			var op:Operation = new Operation(target, opFunction, argArray, parallel);
			allOpArr.push(op);
			opArr.push(op);
			target.addEventListener(OperationEvent.COMPLETE, opCpt/*, false, 0, true*/);
			
			if (canExe || (parallel && curOp.parallel))
			{
				exeOperation();
			}
		}

		public function startExe():void
		{
			_isExeing = true;
			if (canExe && opArr.length)
			{
				exeOperation();
			}
		}

		public function stopExe():void
		{
			_isExeing = false;
		}

		private function opCpt(e:OperationEvent):void
		{
			//防止不同的Operation相同的target
//			(e.target as IEventDispatcher).removeEventListener(OperationEvent.COMPLETE, opCpt);

			var isParallel:Boolean;
			var isParallelComplete:Boolean = true;
			var op:Operation;
			
			for each(op in parallelArr)
			{
				if(op.target == e.target && op.isExeing && !op.isComplete && !isParallel)
				{
					isParallel = true;
					op.isComplete = true;
				}
				if (!op.isComplete)
				{
					isParallelComplete = false;
				}
			}
		
			if(isParallel)
			{
				if(isParallelComplete)
				{
					parallelArr.length = 0;
					canExe = true;
					exeOperation();
				}
			}
			else
			{
				canExe = true;
				exeOperation();
			}
		}

		public function pop():Operation
		{
			return opArr.pop();
		}

		//取出第一个操作执行，然后检查能否继续执行
		public function exeOperation():void
		{
			if(!_isExeing)
			{
				return;
			}
			if (opArr.length == 0)
			{
				clear();
				this.dispatchEvent(new OperationEvent(OperationEvent.ALL_COMPLETE));
				this.dispatchEvent(new OperationEvent(OperationEvent.COMPLETE));
				return;
			}
			//必须在这里，因为Operation里面也可能添加队列
			canExe = false;

			var op:Operation = opArr[0];
			if (op.parallel)
			{
				while (opArr.length)
				{
					op = opArr[0];
					if (!op.parallel)
					{
						break;
					}

					curOp = op;
					parallelArr.push(op);
					opArr.shift();
					op.exeOperation();
				}
			}
			else
			{
				curOp = op;
				opArr.shift();
				op.exeOperation();
			}
		}

		/**
		 * 只受startExe和stopExe函数的控制
		 * @return
		 */
		public function get isExeing():Boolean
		{
			return _isExeing;
		}
	}
}